#pragma once

#include <iostream>
#include <vector>
#include <pthread.h>
#include "Sem.hpp"
#include "Mutex.hpp"

namespace RingBufferModule
{
    using namespace SemModule;
    using namespace LockModule;
    template <typename T>
    class RingBuffer
    {
    public:
        RingBuffer(int cap):_ring(cap),_cap(cap),_p_step(0),_c_step(0),_datasem(0),_spacesem(cap)
        {
        }
        void Equeue(const T&in)
        {
            _spacesem.P();
            {
                LockGuard lockguard(_p_lock);
                _ring[_p_step] = in;
                _p_step++;
                _p_step %= _cap;
            }
            _datasem.V();
        }
        void Pop(T* out)
        {
            _datasem.P();
            {
                LockGuard lockguard(_c_lock);
                *out = _ring[_c_step];
                _c_step++;
                _c_step %= _cap;
            }
            _spacesem.V();
        }
        ~RingBuffer()
        {
        }
    private:
        std::vector<T> _ring;// 环， 临界资源
        int _cap;// 总容量
        int _p_step;// 生产者位置
        int _c_step;// 消费位置
        Sem _datasem;// 数据信号量
        Sem _spacesem;// 空间信号量
        Mutex _p_lock;
        Mutex _c_lock;
    };
}